import random
import redis
from faker import Faker
import time

zset_key = "chinese_names"
# 定义获取中文
fake = Faker("zh_CN")


'''
fake.last_name() 函数生成一个随机的中文姓氏， fake.first_name() 函数生成一个随机的中文名字字符。
随机生成的名字长度为 1-3 个字符，最终返回的完整的姓名长度为 2 到 4 个字符。
'''
def generate_two_to_four_char_name():
    # 使用 fake 库生成一个随机的姓氏
    last_name = fake.last_name()
    # 随机生成名字长度，长度为 1-3 的名字
    name_length = random.randint(1, 3)
    # 初始化名字为空字符串
    first_name = ''
    # 循环直到名字长度达到指定长度
    while len(first_name) < name_length:
        # 从 fake 库中随机选择一个名字字符
        first_name += fake.random_element(elements=fake.first_name())
    # 返回完整的姓名，长度为 2 到 4 个字符
    return last_name + first_name[:name_length]


'''
将一个名字加入到 Redis Zset 中，并保证该名字在 Zset 中的唯一性。
函数的实现使用 Redis Pipeline，可以提高性能。
在向 Zset 中添加名字之前，函数首先监控 Zset，如果该名字已经存在于 Zset 中，则不做任何操作，否则将名字和一个独一无二的分数（使用时间戳）一起加入到 Zset 中。
在使用 Pipeline 进行事务提交时，需要注意在执行 execute() 函数之前必须先调用 multi() 函数开始事务。
如果在执行事务过程中发现 Zset 被修改，则需要重新开始循环。
'''
def add_name_to_redis(redis_client, name):
    # 创建 Redis Pipeline
    pipe = redis_client.pipeline()

    # 开始循环
    while True:
        try:
            # 监控 Redis Zset
            pipe.watch(zset_key)
            
            # 如果名字不存在
            if pipe.zrank(zset_key, name) is None:
                # 开始事务
                pipe.multi()
                # 生成独一无二的分数
                unique_score = time.time()
                # 将名字和分数加入 Zset
                pipe.zadd(zset_key, {name: unique_score})
                # 提交事务
                pipe.execute()
                # 跳出循环
                break
            # 如果名字已经存在
            else:
                # 取消监控
                pipe.unwatch()
                # 跳出循环
                break
        # 如果 Redis Zset 被修改
        except redis.WatchError:
            # 继续循环
            continue


def main():
    # 初始化 Redis 客户端
    redis_client = redis.Redis(host='127.0.0.1', port=6379, db=0)

    while True:
        # 生成随机名字，并将其加入 Redis zset 中
        name = generate_two_to_four_char_name()
        add_name_to_redis(redis_client, name)
        # 打印加入的随机名字
        print(f"Added name: {name}")


if __name__ == "__main__":
    main()
